/* Copyright (c) 2022-2025 Qualcomm Technologies International, Ltd. */
/* %%version */

#include "csr_synergy.h"

#ifndef EXCLUDE_GATT_XPAN_CLIENT_MODULE

#include "gatt_xpan_client_discovery.h"
#include "gatt_xpan_client_debug.h"
#include "gatt_xpan_client.h"
#include "gatt_xpan_client_uuid.h"
#include "gatt_xpan_client_init.h"
#include "gatt_xpan_client_common.h"
#include "gatt_xpan_client_private.h"

#include "csr_bt_gatt_lib.h"
#include "csr_bt_uuids.h"

#define UUID_LENGTH 128

static CsrBtUuid128 storedSsid                   = GATT_XPAN_CLIENT_UUID_STORED_SSID;
static CsrBtUuid128 ipv4Addresses                = GATT_XPAN_CLIENT_UUID_IPV4_ADDRESSES;
static CsrBtUuid128 ipv6Addresses                = GATT_XPAN_CLIENT_UUID_IPV6_ADDRESSES;
static CsrBtUuid128 l2capTcpPort                 = GATT_XPAN_CLIENT_UUID_L2CAP_TCP_PORT;
static CsrBtUuid128 udpPort                      = GATT_XPAN_CLIENT_UUID_UDP_PORT;
static CsrBtUuid128 mdnsSrv                      = GATT_XPAN_CLIENT_UUID_MDNS_SRV;
static CsrBtUuid128 twtConfiguration             = GATT_XPAN_CLIENT_UUID_TWT_CONFIGURATION;
static CsrBtUuid128 connectedDevices             = GATT_XPAN_CLIENT_UUID_CONNECTED_DEVICES;
static CsrBtUuid128 clearToSend                  = GATT_XPAN_CLIENT_UUID_CLEAR_TO_SEND;
static CsrBtUuid128 xpanControlPoint             = GATT_XPAN_CLIENT_UUID_XPAN_CONTROL_POINT;
static CsrBtUuid128 bearerPreference             = GATT_XPAN_CLIENT_UUID_BEARER_PREFERENCE;
static CsrBtUuid128 macAddresses                 = GATT_XPAN_CLIENT_UUID_MAC_ADDRESSES;
static CsrBtUuid128 sapPowerState                = GATT_XPAN_CLIENT_UUID_SAP_POWER_STATE;
static CsrBtUuid128 serverFeatures               = GATT_XPAN_CLIENT_UUID_SERVER_FEATURES;
static CsrBtUuid128 audioBearerSwitchResponse    = GATT_XPAN_CLIENT_UUID_AUDIO_BEARER_SWITCH_RESPONSE;
static CsrBtUuid128 numDevicesPresent            = GATT_XPAN_CLIENT_UUID_NUM_DEVICES_PRESENT;
static CsrBtUuid128 voiceBackChannelPeriodicity  = GATT_XPAN_CLIENT_UUID_VOICE_BACK_CHANNEL_PERIODICITY;
static CsrBtUuid128 requestWiFiScanResults       = GATT_XPAN_CLIENT_UUID_REQUEST_WIFI_SCAN_RESULTS;
static CsrBtUuid128 roamingRequestResponse       = GATT_XPAN_CLIENT_UUID_ROAMING_REQUEST_RESPONSE;

static CsrBool compareCsrBtUuid128(CsrBtUuid128 first, CsrBtUuid128 second)
{
    return CsrMemCmp(first, second, CSR_BT_UUID128_SIZE) == 0;
}
/****************************************************************************/
void xpanClientHandleDiscoverAllCharacteristicsResp(GXPANC *gattXpanClient,
                                                    const GATT_MANAGER_DISCOVER_ALL_CHARACTERISTICS_CFM_T *cfm)
{

    GATT_XPAN_CLIENT_INFO("GXPANC: DiscoverAllChar Rsp status=[%u] handle=[0x%x] uuid=[0x%lx] more=[%u]\n",
                           cfm->status,
                           cfm->handle,
                           cfm->uuid,
                           cfm->more_to_come);

    if (cfm->status == CSR_BT_GATT_RESULT_SUCCESS)
    {
        if (cfm->uuid_type == ATT_UUID128)
        {
            CsrBtUuid128 cfmUuid;

            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[0], &(cfmUuid[12]));
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[1], &(cfmUuid[8]));
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[2], &(cfmUuid[4]));
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[3], (cfmUuid));

            if (compareCsrBtUuid128(storedSsid, cfmUuid))
            {
                gattXpanClient->handles.storedSsidHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Stored SSID : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: STORED_SSID cid=[0x%x] handle=[0x%x]\n",
                                       cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(ipv4Addresses, cfmUuid))
            {
                gattXpanClient->handles.Ipv4AddressHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" IPV4 Adrress : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: IPV4_ADDRESS cid=[0x%x] handle=[0x%x]\n",
                                       cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(ipv6Addresses, cfmUuid))
            {
                gattXpanClient->handles.Ipv6AddressHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" IPV6 Adrress : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: IPV6_ADDRESS cid=[0x%x] handle=[0x%x]\n",
                                   cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(l2capTcpPort, cfmUuid))
            {
                gattXpanClient->handles.L2capTcpPortHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" L2cap TCP Port : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: L2CAP_TCP_PORT cid=[0x%x] handle=[0x%x]\n",
                               cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(udpPort, cfmUuid))
            {
                gattXpanClient->handles.UdpPortHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Udp Port : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: UDP_PORT cid=[0x%x] handle=[0x%x]\n",
                           cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(mdnsSrv, cfmUuid))
            {
                gattXpanClient->handles.MDnsSrvUuidHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Mdns SRV UUID : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: MDNS_SRV_UUID cid=[0x%x] handle=[0x%x]\n",
                       cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(twtConfiguration, cfmUuid))
            {
                gattXpanClient->handles.TwtConfigurationHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" TWT Configuration : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: TWT_CONFIGURATION cid=[0x%x] handle=[0x%x]\n",
                                   cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(connectedDevices, cfmUuid))
            {
                gattXpanClient->handles.ConnectedDevicesHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Connected Devices : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: CONNECTED_DEVICES cid=[0x%x] handle=[0x%x]\n",
                               cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(clearToSend, cfmUuid))
            {
                gattXpanClient->handles.ClearToSendHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Clear To Send : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: CLEAR_TO_SEND cid=[0x%x] handle=[0x%x]\n",
                           cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(xpanControlPoint, cfmUuid))
            {
                gattXpanClient->handles.controlPointHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" XPAN Control Point : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: XPAN_CONTROL_POINT cid=[0x%x] handle=[0x%x]\n",
                       cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(bearerPreference, cfmUuid))
            {
                gattXpanClient->handles.BearerPreferenceHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Bearer Preference : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: BEARER_PREFERENCE cid=[0x%x] handle=[0x%x]\n",
                   cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(macAddresses, cfmUuid))
            {
                gattXpanClient->handles.MacAddressHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" MAC Address : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: MAC_ADDRESSES cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(sapPowerState, cfmUuid))
            {
                gattXpanClient->handles.RequestedSapPowerStateHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Sap Power State : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: SAP_POWER_STATE cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(serverFeatures, cfmUuid))
            {
                gattXpanClient->handles.serverFeaturesHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Server Features : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: SERVER_FEATURES cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(audioBearerSwitchResponse, cfmUuid))
            {
                gattXpanClient->handles.audioBearerSwitchResponseHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Audio Bearer Switch Response : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: AUDIO_BEARER_SWITCH_RESPONSE cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(numDevicesPresent, cfmUuid))
            {
                gattXpanClient->handles.numDevicesPresentHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Num Devices Present : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: NUM_DEVICES_PRESENT cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(voiceBackChannelPeriodicity, cfmUuid))
            {
                gattXpanClient->handles.voiceBackChannelPeriodicityHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Voice Back Channel Periodicity : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: VOICE_BACK_CHANNEL_PERIODICITY cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(requestWiFiScanResults, cfmUuid))
            {
                gattXpanClient->handles.requestWiFiScanResultsHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Request Wifi Scan Results : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: REQUEST WIFI SCAN RESULTS cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
            else if (compareCsrBtUuid128(roamingRequestResponse, cfmUuid))
            {
                gattXpanClient->handles.roamingRequestResponseHandle = cfm->handle;
                GATT_XPAN_CLIENT_INFO(" Roaming Request Response : Handle = (%x)\n ", cfm->handle);
                GATT_XPAN_CLIENT_INFO("GXPANC: ROAMING REQUEST RESPONSE cid=[0x%x] handle=[0x%x]\n",
                    cfm->cid, cfm->handle);
            }
        }

        if (!cfm->more_to_come)
        {
            /*All characteristics are Mandatory */
            if (!gattXpanClient->handles.storedSsidHandle ||
                !gattXpanClient->handles.Ipv4AddressHandle ||
                !gattXpanClient->handles.Ipv6AddressHandle ||
                !gattXpanClient->handles.L2capTcpPortHandle ||
                !gattXpanClient->handles.UdpPortHandle ||
                !gattXpanClient->handles.MDnsSrvUuidHandle||
                !gattXpanClient->handles.TwtConfigurationHandle ||
                !gattXpanClient->handles.ConnectedDevicesHandle ||
                !gattXpanClient->handles.ClearToSendHandle ||
                !gattXpanClient->handles.controlPointHandle ||
                !gattXpanClient->handles.BearerPreferenceHandle ||
                !gattXpanClient->handles.MacAddressHandle ||
                !gattXpanClient->handles.RequestedSapPowerStateHandle ||
                !gattXpanClient->handles.serverFeaturesHandle ||
                !gattXpanClient->handles.audioBearerSwitchResponseHandle ||
                !gattXpanClient->handles.numDevicesPresentHandle ||
                !gattXpanClient->handles.voiceBackChannelPeriodicityHandle ||
                !gattXpanClient->handles.requestWiFiScanResultsHandle ||
                !gattXpanClient->handles.roamingRequestResponseHandle)
            {
                /* One of the XPAN characteristic is not found, initialization complete */
                gattXpanClientSendInitCfm(gattXpanClient, GATT_XPAN_CLIENT_STATUS_DISCOVERY_ERR);
                if(!ServiceHandleFreeInstanceData(gattXpanClient->srvcElem->service_handle))
                {
                    GATT_XPAN_CLIENT_PANIC("Freeing of memory instance failed\n");
                }
            }
            else
            {
                /* All XPAN characteristics found, find the descriptors */
                xpanClientdiscoverAllXpanCharacteristicDescriptors(gattXpanClient);
            }
        }
    }
    else
    {
        gattXpanClientSendInitCfm(gattXpanClient, GATT_XPAN_CLIENT_STATUS_DISCOVERY_ERR);
        if(!ServiceHandleFreeInstanceData(gattXpanClient->srvcElem->service_handle))
        {
            GATT_XPAN_CLIENT_PANIC("Freeing of memory instance failed\n");
        }
    }
}

/****************************************************************************/
void xpanClientdiscoverAllXpanCharacteristicDescriptors(GXPANC *gattXpanClient)
{
    CsrBtGattDiscoverAllCharacDescriptorsReqSend(gattXpanClient->srvcElem->gattId,
                                                 gattXpanClient->srvcElem->cid,
                                                 gattXpanClient->clientData.startHandle + 1,
                                                 gattXpanClient->clientData.endHandle);
}

/****************************************************************************/
void xpanClientHandleDiscoverAllCharacteristicDescriptorsResp(GXPANC *gattXpanClient,
                                                              const GATT_MANAGER_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM_T *cfm)
{
    GATT_XPAN_CLIENT_INFO("GXPANC: DiscoverAllDesc Rsp status=[%u] handle=[0x%x] uuid[0]=[0x%lx] more=[%u]\n",
                           cfm->status, cfm->handle,  cfm->uuid[0], cfm->more_to_come);

    if (cfm->status == CSR_BT_GATT_RESULT_SUCCESS)
    {
        if(cfm->uuid_type == ATT_UUID16)
        {
            GATT_XPAN_CLIENT_INFO("GATT_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM: Success! Handle:0x%04x UUID: 0x%04x\n",
                      cfm->handle, cfm->uuid[0]);

            switch(cfm->uuid[0])
            {
                case CSR_BT_GATT_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC:
                {
                    GATT_XPAN_CLIENT_INFO("GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_UUID: UUID16: 0x%04x, Desc handle:0x%04x\n",
                                           cfm->uuid[0], gattXpanClient->nextDescriptorHandle);

                    if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, storedSsid))
                    {
                        gattXpanClient->handles.storedSsidCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, ipv4Addresses))
                    {
                        gattXpanClient->handles.Ipv4AddressCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, ipv6Addresses))
                    {
                        gattXpanClient->handles.Ipv6AddressCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, l2capTcpPort))
                    {
                       gattXpanClient->handles.L2capTcpPortCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, udpPort))
                    {
                        gattXpanClient->handles.UdpPortCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, connectedDevices))
                    {
                        gattXpanClient->handles.ConnectedDevicesCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, clearToSend))
                    {
                        gattXpanClient->handles.ClearToSendCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, bearerPreference))
                    {
                       gattXpanClient->handles.BearerPreferenceCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, macAddresses))
                    {
                        gattXpanClient->handles.MacAddressCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, sapPowerState))
                    {
                        gattXpanClient->handles.RequestedSapPowerStateCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, serverFeatures))
                    {
                       gattXpanClient->handles.serverFeaturesCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, audioBearerSwitchResponse))
                    {
                        gattXpanClient->handles.audioBearerSwitchResponseCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, numDevicesPresent))
                    {
                        gattXpanClient->handles.numDevicesPresentCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, voiceBackChannelPeriodicity))
                    {
                        gattXpanClient->handles.voiceBackChannelPeriodicityCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, requestWiFiScanResults))
                    {
                        gattXpanClient->handles.requestWiFiScanResultsCccHandle = cfm->handle;
                    }
                    else if (compareCsrBtUuid128(gattXpanClient->nextDescriptorHandle, roamingRequestResponse))
                    {
                        gattXpanClient->handles.roamingRequestResponseCccHandle = cfm->handle;
                    }
                    /* reset the handle */
                    CsrMemSet(gattXpanClient->nextDescriptorHandle, 0, sizeof(CsrBtUuid128));

                }
                break;

                default:
                    break;
            }
        }
        else if(cfm->uuid_type == ATT_UUID32)
        {
            GATT_XPAN_CLIENT_INFO("GATT_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM: Success! Handle:0x%04x UUID32: 0x%08x 0x%08x\n",
                      cfm->handle, cfm->uuid[0], cfm->uuid[1]);
        }
        else if (cfm->uuid_type == ATT_UUID128)
        {
            CsrBtUuid128 cfmUuid;
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[0], &(cfmUuid[12]));
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[1], &(cfmUuid[8]));
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[2], &(cfmUuid[4]));
            CSR_COPY_UINT32_TO_BIG_ENDIAN(cfm->uuid[3], (cfmUuid));

            GATT_XPAN_CLIENT_INFO("GATT_DISCOVER_ALL_CHARACTERISTIC_DESCRIPTORS_CFM: Success! Handle:0x%04x UUID: [0]=0x%08x [1]=0x%08x [2]=0x%08x [3]=0x%08x\n",
                      cfm->handle,  cfmUuid[0],  cfmUuid[1],  cfmUuid[2],  cfmUuid[3]);

            /* Characteristics that have a Client Characteristic Config */
            if(compareCsrBtUuid128(cfmUuid, storedSsid) ||
               compareCsrBtUuid128(cfmUuid, ipv4Addresses) ||
               compareCsrBtUuid128(cfmUuid, ipv6Addresses) ||
               compareCsrBtUuid128(cfmUuid, l2capTcpPort) ||
               compareCsrBtUuid128(cfmUuid, udpPort) ||
               compareCsrBtUuid128(cfmUuid, mdnsSrv) ||
               compareCsrBtUuid128(cfmUuid, twtConfiguration) ||
               compareCsrBtUuid128(cfmUuid, connectedDevices) ||
               compareCsrBtUuid128(cfmUuid, clearToSend) ||
               compareCsrBtUuid128(cfmUuid, xpanControlPoint) ||
               compareCsrBtUuid128(cfmUuid, bearerPreference) ||
               compareCsrBtUuid128(cfmUuid, macAddresses) ||
               compareCsrBtUuid128(cfmUuid, sapPowerState) ||
               compareCsrBtUuid128(cfmUuid, serverFeatures) ||
               compareCsrBtUuid128(cfmUuid, audioBearerSwitchResponse) ||
               compareCsrBtUuid128(cfmUuid, numDevicesPresent) ||
               compareCsrBtUuid128(cfmUuid, voiceBackChannelPeriodicity) ||
               compareCsrBtUuid128(cfmUuid, requestWiFiScanResults) ||
               compareCsrBtUuid128(cfmUuid, roamingRequestResponse))
            {
                    GATT_XPAN_CLIENT_INFO("GXPANC: Descriptor UUID: 0x%08x 0x%08x 0x%08x 0x%08x\n", cfm->uuid[0],cfm->uuid[1],cfm->uuid[2],cfm->uuid[3]);
                    SynMemMoveS(gattXpanClient->nextDescriptorHandle, sizeof(CsrBtUuid128),
                                cfmUuid, sizeof(CsrBtUuid128));
            }
        }
    }
    else
    {
        GATT_XPAN_CLIENT_ERROR("Discovery of all the XPAN Server descriptors failed! Status: %d", cfm->status);
    }

    if (!cfm->more_to_come)
    {
        if (!gattXpanClient->handles.storedSsidCccHandle ||
            !gattXpanClient->handles.Ipv4AddressCccHandle ||
            !gattXpanClient->handles.Ipv6AddressCccHandle ||
            !gattXpanClient->handles.L2capTcpPortCccHandle ||
            !gattXpanClient->handles.UdpPortCccHandle ||
            !gattXpanClient->handles.ConnectedDevicesCccHandle ||
            !gattXpanClient->handles.ClearToSendCccHandle ||
            !gattXpanClient->handles.BearerPreferenceCccHandle ||
            !gattXpanClient->handles.RequestedSapPowerStateCccHandle ||
            !gattXpanClient->handles.serverFeaturesCccHandle ||
            !gattXpanClient->handles.audioBearerSwitchResponseCccHandle ||
            !gattXpanClient->handles.numDevicesPresentCccHandle ||
            !gattXpanClient->handles.voiceBackChannelPeriodicityCccHandle ||
            !gattXpanClient->handles.requestWiFiScanResultsCccHandle ||
            !gattXpanClient->handles.roamingRequestResponseCccHandle)
        {
            GATT_XPAN_CLIENT_ERROR("XPAN: Client characteristic discovery - FAILED\n");
            gattXpanClientSendInitCfm(gattXpanClient, GATT_XPAN_CLIENT_STATUS_DISCOVERY_ERR);
            if(!ServiceHandleFreeInstanceData(gattXpanClient->srvcElem->service_handle))
            {
                GATT_XPAN_CLIENT_PANIC("Freeing of memory instance failed\n");
            }
        }
        else
        {
            GATT_XPAN_CLIENT_INFO("GXPANC: Client characteristic discovery - SUCCESS\n");
            gattXpanClientSendInitCfm(gattXpanClient, GATT_XPAN_CLIENT_STATUS_SUCCESS);
            gattXpanClient->clientDataIsSet = TRUE;
        }
    }
}

#endif /* EXCLUDE_GATT_XPAN_CLIENT_MODULE */